package com.mm.fam.web.service.impl;

import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.segments.MergeSegments;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mm.fam.common.utils.LoggerUtils;
import com.mm.fam.web.base.ResponseModel;
import com.mm.fam.web.base.ResponseUtil;
import com.mm.fam.web.entity.SysMenu;
import com.mm.fam.web.entity.SysRoleMenu;
import com.mm.fam.web.entity.SysUserOrganization;
import com.mm.fam.web.entity.ins.AuthMenuTreeIns;
import com.mm.fam.web.mapper.SysMenuMapper;
import com.mm.fam.web.mapper.SysRoleMenuMapper;
import com.mm.fam.web.mapper.SysUserOrganizationMapper;
import com.mm.fam.web.service.SysMenuService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author zt
 * @since 2018-09-29
 */
@Service
public class SysMenuServiceImpl extends ServiceImpl<SysMenuMapper, SysMenu> implements SysMenuService {
    @Autowired
    private SysMenuMapper sysMenuMapper;
    @Autowired
    private SysRoleMenuMapper sysRoleMenuMapper;
    @Autowired
    private SysUserOrganizationMapper sysUserOrganizationMapper;


    @Override
    public List<SysMenu> getMenuByUserId(Integer userId) {
        return sysMenuMapper.getMenuByUserId(userId);
    }

    @Override
    public ResponseEntity<ResponseModel<Object>> saveMenu(SysMenu menu){
        ResponseEntity<ResponseModel<Object>> re = null;
        Date data = new Date();
        if (menu.getId() == null) {
            menu.setCreateTime(data);
            menu.setUpdateTime(data);
            save(menu);
            re = ResponseUtil.success(null);
        } else {
            menu.setUpdateTime(data);
            updateById(menu);
            re = ResponseUtil.success(null);
        }
        return re;
    }

    @Override
    public List<AuthMenuTreeIns> getMenuTreeByUserId(Integer userId) {
        List<AuthMenuTreeIns> menuTreeByUserId = null;
        try {
            menuTreeByUserId = sysMenuMapper.getMenuTreeByUserId(userId);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return menuTreeByUserId;
    }

    @Override
    public IPage<AuthMenuTreeIns> getMenuTree(SysMenu menu) {
        Map<String, Object> map = new HashMap<>();
        Page<AuthMenuTreeIns> page = new Page(menu.getCurrent(), menu.getPageSize());
        try {
            map.put("parentId", menu.getParentId());
            if (!StringUtils.isEmpty(menu.getName())) {
                map.put("query_name", menu.getName().trim());
            } else {
                map.put("query_name", "");
            }
            map.put("page", page);
            List<AuthMenuTreeIns> menuTree = sysMenuMapper.getMenuTree(map);
            page.setRecords(menuTree);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return page;
    }

    @Override
    public List<SysMenu> getMenuByRoleId(String roleId) {
        return sysMenuMapper.getMenuByRoleId(roleId);
    }

    @Override
    public List<SysMenu> getMenuByRoleIds(List<Integer> roleIds) {
        return sysMenuMapper.getMenuByRoleIds(roleIds);
    }

    @Override
    public IPage<SysMenu> page(int pageNum, int pageSize, String search, Integer parentId) {


        QueryWrapper<SysMenu> wrapper = new QueryWrapper<>();
        search = StringUtils.trim(search);
        if (StringUtils.isNoneEmpty(search)) {
            wrapper.like(true, "name", "%" + search + "%");
        }
        if (parentId != null) {
            wrapper.eq(true, "parent_id", parentId);
        }
        wrapper.orderBy(true, true, "level");
        wrapper.orderBy(true, true, "id");


        Page<SysMenu> page = new Page<>(pageNum, pageSize);

        return sysMenuMapper.selectPage(page, wrapper);
    }

    @Override
    public String deleteBatch(List<String> ids) throws RuntimeException {

        try {
            sysMenuMapper.deleteBatchIds(ids);
        } catch (Exception e) {
            LoggerUtils.error(getClass(), "批量删除菜单失败:" + e.getMessage());
            throw new RuntimeException("删除菜单失败");
        }
        return "删除菜单成功";
    }

    //根据用户id删除菜单s
    @Override
    public boolean deleteMemuById(String id) {
        //查询是否有子级菜单
        int parentIdByMenuId = sysRoleMenuMapper.findParentIdByMenuId(id);
        if (parentIdByMenuId == 0) {
            //根据用户id查询该菜单是否被占用
            int roleByMenuId = sysRoleMenuMapper.findRoleByMenuId(id);
            if (roleByMenuId <= 0) {
                int deleteMenuById = sysMenuMapper.deleteMenuById(id);
                if (deleteMenuById > 0) {
                    return true;
                } else {
                    throw new RuntimeException("菜单操作失败");
                }

            } else {
                LoggerUtils.error(getClass(), "删除失败，请检查菜单是否被占用:");
                throw new RuntimeException("菜单操作失败");

            }
        } else {
            LoggerUtils.error(getClass(), "删除失败，请检查菜单是否被占用:");
            throw new RuntimeException("菜单操作失败");

        }
    }

    //***************************** chenyu add begin ***************************************
    @Override
    public ResponseEntity<ResponseModel<List<SysMenu>>> queryMenuTree(String search) {
        ResponseEntity<ResponseModel<List<SysMenu>>> re = null;
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("status", 1);
        List<SysMenu> sysMenus = sysMenuMapper.queryListByCondition(paramMap);
        Map<String, Object> resultMap = new HashMap<>();
        List<SysMenu> tree = this.findTree(sysMenus, 0);

        return ResponseUtil.success(tree);
    }

    @Override
    public ResponseEntity<ResponseModel<List<String>>> queryRoleOwnMenu(Integer roleId) {

        Wrapper<SysRoleMenu> w = new Wrapper<SysRoleMenu>() {
            @Override
            public SysRoleMenu getEntity() {
                SysRoleMenu srm = new SysRoleMenu();
                srm.setRoleId(roleId);
                return srm;
            }

            @Override
            public MergeSegments getExpression() {
                return null;
            }

            @Override
            public String getCustomSqlSegment() {
                return null;
            }

            @Override
            public String getSqlSegment() {
                return null;
            }
        };
        List<SysRoleMenu> sysRoleMenus = sysRoleMenuMapper.selectList(w);
        List<String> menuIds = new ArrayList<>();
        for (SysRoleMenu srm: sysRoleMenus) {
            menuIds.add(srm.getMenuId().toString());
        }

        return ResponseUtil.success(menuIds);
    }

    @Override
    public ResponseEntity<ResponseModel<Object>> updateRoleOwnMenu(Integer roleId, String menuIds) {
        ResponseEntity<ResponseModel<Object>> re = null;

        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("role_id", roleId);
        //清空现有角色权限
        sysRoleMenuMapper.deleteByMap(paramMap);

        //新增权限
        for(String menuId : menuIds.split(",")){
            SysRoleMenu srm = new SysRoleMenu();
            srm.setRoleId(roleId);
            srm.setMenuId(Integer.valueOf(menuId));
            sysRoleMenuMapper.insert(srm);
        }

        return ResponseUtil.success(null);
    }

    @Override
    public ResponseEntity<ResponseModel<Object>> queryDynamicMenu(Integer roldId) {
        ResponseEntity<ResponseModel<Object>> re = null;
        Map<String, Object> resultMap = new HashMap<>();
        Map<String, Object> paramMap = new HashMap<>();
        List<Map<String, Object>> resultList = new ArrayList<>();

        List<Integer> roleIds = new ArrayList<>();
        roleIds.add(roldId);

        List<SysMenu> roleMenuList = sysMenuMapper.getMenuByRoleIds(roleIds);
        List<SysMenu> allMenuList = sysMenuMapper.queryListByCondition(paramMap);

        //进行菜单分类
        List<SysMenu> parentMenuList = new ArrayList<>();
        List<SysMenu> childMenuList = new ArrayList<>();
        for(SysMenu roleMenu : roleMenuList){
            if(roleMenu.getParentId().equals(0)){
                parentMenuList.add(roleMenu);
            }else{
                childMenuList.add(roleMenu);
            }
        }

        //筛选出已经有父级菜单的数据
        for(SysMenu parentMenu : parentMenuList){
            Iterator<SysMenu> it = childMenuList.iterator();
            while (it.hasNext()){
                SysMenu childMenu = it.next();
                if(parentMenu.getId() == childMenu.getParentId()){
                    it.remove();
                }
            }
        }

        //根据childMenu 向原始数据中补全父级菜单
        for(SysMenu childMenu : childMenuList){
            for(SysMenu allMenu : allMenuList){
                if(childMenu.getParentId() == allMenu.getId() && !roleMenuList.contains(allMenu)){
                    roleMenuList.add(allMenu);
                }
            }
        }

        //组织树结构
        List<Map<String, Object>> oneLevelMenuList = new ArrayList<>();
        for(SysMenu sm1: roleMenuList){
            if(sm1.getParentId().equals(0)){
                List<Map<String, Object>> twoLevelMenuList = new ArrayList<>();

                for(SysMenu sm2 : roleMenuList){
                    if(sm2.getParentId().equals(sm1.getId())){
                        Map<String, Object> item2 = new HashMap<>();
                        item2.put("title",sm2.getTitle());
                        item2.put("key",sm2.getKey());
                        item2.put("component",sm2.getComponent());
                        item2.put("icon", sm2.getIcon());
                        item2.put("hidden", sm2.getHidden());
                        item2.put("sorter", sm2.getSorter());
                        twoLevelMenuList.add(item2);
                    }
                }

                Map<String, Object> item1 = new HashMap<>();
                item1.put("title",sm1.getTitle());
                item1.put("key", sm1.getKey());
                item1.put("component",sm1.getComponent());
                item1.put("icon",sm1.getIcon());
                item1.put("children",twoLevelMenuList);
                item1.put("sorter", sm1.getSorter());
                oneLevelMenuList.add(item1);
            }
        }

        Collections.sort(oneLevelMenuList, new Comparator<Map<String, Object>>() {
            @Override
            public int compare(Map<String, Object> o1, Map<String, Object> o2) {
                Integer name1 = Integer.valueOf(o1.get("sorter").toString()) ;
                Integer name2 = Integer.valueOf(o2.get("sorter").toString()) ;
                return name1.compareTo(name2);
            }
        });

        for (Map<String, Object> two : oneLevelMenuList){
            Collections.sort((List) two.get("children"), new Comparator<Map<String, Object>>() {
                @Override
                public int compare(Map<String, Object> o1, Map<String, Object> o2) {
                    Integer name1 = Integer.valueOf(o1.get("sorter").toString()) ;
                    Integer name2 = Integer.valueOf(o2.get("sorter").toString()) ;
                    return name1.compareTo(name2);
                }
            });
        }

        resultMap.put("title", "首页");
        resultMap.put("key", "");
        resultMap.put("name", "index");
        resultMap.put("component", "BasicLayout");
        resultMap.put("redirect", "/dashboard/workplace");
        resultMap.put("children", oneLevelMenuList);
        resultMap.put("sorter", 1);

        resultList.add(resultMap);




        re = ResponseUtil.success(resultList);

        return re;
    }

    @Override
    public List<Integer> queryOrganizationByUserId(Integer userId) {
        List<Integer> organizationIds = new ArrayList<>();
        List<SysUserOrganization> userOrganizationList = sysUserOrganizationMapper.selectList(new QueryWrapper<SysUserOrganization>().eq("user_id", userId));

        for(SysUserOrganization suo : userOrganizationList){
            organizationIds.add(suo.getOrganizationId());
        }
        return organizationIds;
    }

    @Override
    public ResponseEntity<ResponseModel<IPage<SysMenu>>> queryMenuList(Integer pageNo, Integer pageSize, String search) {
        ResponseEntity<ResponseModel<IPage<SysMenu>>> re = null;

        Map<String, Object> paramMap = new HashMap<String, Object>();
        if(search != null){
            paramMap.put("search", '%'+search+'%');
        }

        Page<SysMenu> page = new Page<>(pageNo, pageSize);
        IPage<SysMenu> sysMenuIPage = page.setRecords(sysMenuMapper.queryParentMenu(page, paramMap));

        re = ResponseUtil.success(sysMenuIPage);

        return re;
    }

    @Override
    public ResponseEntity<ResponseModel<List<SysMenu>>> queryParentMenuListNoPage() {
        ResponseEntity<ResponseModel<List<SysMenu>>> re = null;
        List<SysMenu> parentMenuList = sysMenuMapper.selectList(new QueryWrapper<SysMenu>().eq("parent_id", 0));
        re = ResponseUtil.success(parentMenuList);
        return re;
    }

    @Override
    public ResponseEntity<ResponseModel<List<SysMenu>>> queryChildrenMenuListNoPage() {
        ResponseEntity<ResponseModel<List<SysMenu>>> re = null;
        List<SysMenu> parentMenuList = sysMenuMapper.selectList(new QueryWrapper<SysMenu>().ne("parent_id", 0));
        re = ResponseUtil.success(parentMenuList);
        return re;
    }

    /**
     * 格式化菜单树
     * @param sysMenus 原始菜单树
     * @param rootId   根节点
     * @return
     */
    private List<SysMenu> findTree(List<SysMenu> sysMenus, Integer rootId){
        try {
            //查询所有菜单
            List<SysMenu> allMenu = sysMenus;

            //根节点
            List<SysMenu> rootMenu = new ArrayList<SysMenu>();

            for (SysMenu nav : allMenu) {
                if(nav.getParentId().equals(rootId)){//父节点是0的，为根节点。
                    nav.setKey(nav.getId().toString());
                    rootMenu.add(nav);
                }
            }

            /* 根据Menu类的order排序 */
            Collections.sort(rootMenu, order());
            //为根菜单设置子菜单，getClild是递归调用的
            for (SysMenu nav : rootMenu) {
                /* 获取根节点下的所有子节点 使用getChild方法*/
                List<SysMenu> childList = getChild(nav.getId(), allMenu);
                nav.setChildren(childList);//给根节点设置子节点
            }
            return rootMenu;
        } catch (Exception e) {
            e.printStackTrace();
            return new ArrayList<>();
        }
    }

    /**
     * 获取子节点
     * @param id 父节点id
     * @param allMenu 所有菜单列表
     * @return 每个根节点下，所有子菜单列表
     */
    private List<SysMenu> getChild(Integer id,List<SysMenu> allMenu){
        //子菜单
        List<SysMenu> childList = new ArrayList<SysMenu>();
        for (SysMenu nav : allMenu) {
            // 遍历所有节点，将所有菜单的父id与传过来的根节点的id比较
            //相等说明：为该根节点的子节点。
            if(nav.getParentId().equals(id)){
                nav.setKey(nav.getId().toString());
                childList.add(nav);
            }
        }
        //递归
        for (SysMenu nav : childList) {
            nav.setChildren(getChild(nav.getId(), allMenu));
        }
        Collections.sort(childList,order());//排序
        //如果节点下没有子节点，返回一个空List（递归退出）
        if(childList.size() == 0){
            return new ArrayList<SysMenu>();
        }
        return childList;
    }

    /*
     * 排序,根据order排序
     */
    private Comparator<SysMenu> order(){
        Comparator<SysMenu> comparator = new Comparator<SysMenu>() {
            @Override
            public int compare(SysMenu o1, SysMenu o2) {
                if(o1.getSorter() != o2.getSorter()){
                    return o1.getSorter() - o2.getSorter();
                }
                return 0;
            }
        };
        return comparator;
    }





    //***************************** chenyu add end ***************************************
}
